﻿using IGrain;
using Orleans;
using Orleans.Concurrency;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Grains
{
    [Reentrant]
    public class Employee : Grain, IEmployee
    {
        private int _level;
        private IManager _directManager;

        public Task<int> GetLevel()
        {
            return Task.FromResult(_level);
        }

        public Task<IManager> GetManager()
        {
            return Task.FromResult(_directManager);
        }

        public Task Greeting(IEmployee from, string message)
        {
            Console.WriteLine($"{from.GetPrimaryKey().ToString()} said: {message}");
            return Task.CompletedTask;
        }

        public async Task Greeting(GreetingData greetingData)
        {
            Console.WriteLine($"{greetingData.From} said: {greetingData.Message}");
            if (greetingData.Count == 1)
                return;

            var fromEmployee = GrainFactory.GetGrain<IEmployee>(greetingData.From);
            await fromEmployee.Greeting(new GreetingData
            {
                From = this.GetPrimaryKey(),
                Message = "Thanks!",
                Count = greetingData.Count + 1
            });

        }

        public Task Promote(int newLevel)
        {
            _level = newLevel;
            return Task.CompletedTask;
        }

        public Task SetManager(IManager manager)
        {
            _directManager = manager;
            return Task.CompletedTask;
        }
    }

    public class Manager : Grain, IManager
    {
        private IEmployee _me;
        private IList<IEmployee> _reports = new List<IEmployee>();
        public override Task OnActivateAsync()
        {
            _me = this.GrainFactory.GetGrain<IEmployee>(this.GetPrimaryKey());
            return base.OnActivateAsync();
        }

        public async Task AddDirectReport(IEmployee employee)
        {
            _reports.Add(employee);
            await employee.SetManager(this);
            await employee.Greeting(new GreetingData
            {
                From = this.GetPrimaryKey(),
                Message = "Welcome to my team."
            });

        }

        public Task<IEmployee> AsEmployee()
        {
            Console.WriteLine($"AsEmployee#PrimayKey: {this.GetPrimaryKey()}");
            return Task.FromResult(_me);
        }

        public Task<IList<IEmployee>> GetDirectReports()
        {
            return Task.FromResult(_reports);
        }
    }
}
